﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Excel = Microsoft.Office.Interop.Excel;

namespace ConsoleApp3_framwork_
{
    public static class 二维数组扩展
    {
        //public static IEnumerable<TResult> LeftJoin<TOuter, TInner, TKey, TResult>
        //    (this IEnumerable<TOuter> outer,
        //    IEnumerable<dynamic> inner,
        //    Func<TOuter, TKey> outerKeySelector,
        //    Func<dynamic, TKey> innerKeySelector,
        //    Func<TOuter, IEnumerable<dynamic>, TResult> resultSelector)
        //{
        //    return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector);
        //}

        public static void ToRange(this IEnumerable<dynamic> IEnumerable, Excel.Range range)
        {
            IEnumerable.To2DArray().ToRange(range);//aasbbbdsda
        }

        public static void ToRange(this dynamic[,] arr, Excel.Range range)
        {
            range.Resize[arr.GetUpperBound(0) + 1, arr.GetUpperBound(1) + 1].Value = arr;
        }

        public static dynamic[,] To2DArray(this IEnumerable<dynamic> IEnumerable)
        {
            var arr = IEnumerable.ToArray();
            Type t = arr.First().GetType();
            var refPropInfo = t.GetRuntimeProperties().ToArray();
            dynamic[,] result = new dynamic[arr.Length + 1, refPropInfo.Length];
            for (int r = 0; r <= arr.Length; r++)
            {
                for (int c = 0; c < refPropInfo.Length; c++)
                {
                    if (r == 0)
                    {
                        result[r, c] = refPropInfo[c].Name;
                    }
                    else
                    {
                        result[r, c] = refPropInfo[c].GetValue(arr[r - 1]);
                    }
                }
            }
            return result;
        }

        public static IEnumerable<dynamic> AsEnumerable(this dynamic[,] arr, bool useHeaderRow = true)
        {
            var firstRow = true;
            var headrow = new Dictionary<int, string>();
            for (int r = arr.GetLowerBound(0); r <= arr.GetUpperBound(0); r++)
            {
                if (useHeaderRow)
                {
                    if (firstRow)
                    {
                        firstRow = false;
                        for (int c = arr.GetLowerBound(1); c <= arr.GetUpperBound(1); c++)
                            headrow[c] = arr[r, c]?.ToString();
                    }
                    else
                    {
                        IDictionary<string, object> cell = new ExpandoObject();
                        for (int c = arr.GetLowerBound(1); c <= arr.GetUpperBound(1); c++)
                            cell[headrow[c]] = arr[r, c];
                        yield return cell;
                    }
                }
                else
                {
                    IDictionary<string, object> cell = new ExpandoObject();
                    for (int c = arr.GetLowerBound(1); c <= arr.GetUpperBound(1); c++)
                        cell[IntToLetters(c)] = arr[r, c];
                    yield return cell;
                }
            }
        }

        internal static string IntToLetters(int value)
        {
            //value = value + 1;
            string result = string.Empty;
            while (--value >= 0)
            {
                result = (char)('A' + value % 26) + result;
                value /= 26;
            }
            return result;
        }
    }
}